package GUI;

import java.util.ArrayList;
import java.util.Calendar;

import Control.Airport;
import Control.Meteor;
import Control.MilitaryBase;
import Control.UFO;
import Control.WeatherStation;

import com.modestmaps.InteractiveMap;
import com.modestmaps.core.Point2f;
import com.modestmaps.geo.Location;
import com.modestmaps.providers.Microsoft;

import processing.core.PApplet;
import processing.core.PFont;

public class Map {


	float delay =0;
	int widthHeight ;
	float circleWidthHeight;

	//
	// This is a test of the interactive Modest Maps library for Processing
	// the modestmaps.jar in the code folder of this sketch might not be 
	// entirely up to date - you have been warned!
	//

	// this is the only bit that's needed to show a map:
	InteractiveMap map;
	ArrayList<UFO> highLightToDraw = new ArrayList<UFO>();
	Airport airportHighLightToDraw;
	MilitaryBase militaryBaseToDraw;

	PFont font;
	UfoHighLight ufoHighLight = new UfoHighLight();
	boolean gui = true;


	public void draw(float dt) {
		GV.processing.background(0);

		// see if the arrow keys or +/- keys are pressed:
		// (also check space and z, to reset or round zoom levels)
		if (GV.processing.keyPressed) {
			if (GV.processing.key == GV.processing.CODED) {
				if (GV.processing.keyCode == GV.processing.LEFT) {
					map.tx += 20.0/map.sc;
					GV.cluster.createGridData();
				}
				else if (GV.processing.keyCode == GV.processing.RIGHT) {
					map.tx -= 20.0/map.sc;
					GV.cluster.createGridData();
				}
				else if (GV.processing.keyCode == GV.processing.UP) {
					map.ty += 20.0/map.sc;
					GV.cluster.createGridData();
				}
				else if (GV.processing.keyCode == GV.processing.DOWN) {
					map.ty -= 20.0/map.sc;
					GV.cluster.createGridData();
				}
			}  
			else if (GV.processing.key == '+' || GV.processing.key == '=') {
				if(map.sc*1.05<2100){
					map.sc *= 1.05;
					GV.cluster.createGridData();
					GV.checkTotalData();
				}
				ufoHighLight.state=false;

			}
			else if (GV.processing.key == '_' || GV.processing.key == '-' && map.sc > 2) {
				if((map.sc * 1.0/1.05)>15){
					map.sc *= 1.0/1.05;
					GV.cluster.createGridData();
					GV.checkTotalData();
				}
				ufoHighLight.state=false;

			}
		}

		// draw the map:
		map.draw();
		// (that's it! really... everything else is interactions now)

		GV.processing.smooth();

		// draw all the buttons and check for mouse-over
		boolean hand = false;
		//  if (gui) {
		//    for (int i = 0; i < buttons.length; i++) {
		//      buttons[i].draw();
		//      hand = hand || buttons[i].mouseOver();
		//    }
		//  }

		// if we're over a button, use the finger pointer
		// otherwise use the cross
		// (I wish Java had the open/closed hand for "move" cursors)
		GV.processing.cursor(hand ? GV.processing.HAND : GV.processing.CROSS);



		if (gui) {
			GV.processing.textFont(font, 12);

			// grab the lat/lon location under the mouse point:
			Location location = map.pointLocation(GV.processing.mouseX, GV.processing.mouseY);

			// draw the mouse location, bottom left:
			GV.processing.fill(0);
			GV.processing.noStroke();
			GV.processing.rect(5, GV.processing.height-5-GV.processing.g.textSize, GV.processing.textWidth("mouse: " + location), GV.processing.g.textSize+GV.processing.textDescent());
			GV.processing.fill(255,255,0);
			GV.processing.textAlign(GV.processing.LEFT, GV.processing.BOTTOM);
			GV.processing.text("mouse: " + location, 5, GV.processing.height-5);

			// grab the center
			location = map.pointLocation(GV.processing.width/2, GV.processing.height/2);

			// draw the center location, bottom right:
			GV.processing. fill(0);
			GV.processing.noStroke();
			float rw = GV.processing.textWidth("map: " + location);
			GV.processing.rect(GV.processing.width-5-rw, GV.processing.height-5-GV.processing.g.textSize, rw, GV.processing.g.textSize+GV.processing.textDescent());
			GV.processing.fill(255,255,0);
			GV.processing.textAlign(GV.processing.RIGHT, GV.processing.BOTTOM);
			GV.processing.text("map: " + location, GV.processing.width-5, GV.processing.height-5);

			/*
    location = new Location(51.500, -0.126);
    Point2f p = map.locationPoint(location);

    fill(0,255,128);
    stroke(255,255,0);
    ellipse(p.x, p.y, 10, 10); */
		}  

		//System.out.println((float)map.sc);
		//System.out.println((float)map.tx + " " + (float)map.ty);


		GV.processing.stroke(0,0,0);

		//if the graphs are active do not draw any point
		if(GV.hoursPanel.graphButton.state) return;


		if(GV.hoursPanel.clusterButton.state){//draw cluster data
			GV.cluster.draw();
		}
		else{ //draw normal map points
			delay+=dt;
			if(delay>0.03){
				delay=0;
				drawMapPoints();
			}
			ufoHighLight.draw();
		}

	}


	private void drawMapPoints() {
		widthHeight = (int) ((float)10/6*Math.pow(map.sc, 0.5));
		circleWidthHeight = widthHeight/(float)1.3;
		int widthHeight2 = (int)(widthHeight/(float)1.7); 
		
		//draw meteors
		if(GV.hoursPanel.showMeteorsButton.state)
			for(Meteor m : GV.meteorsToDisplay){
				Point2f p = map.locationPoint(new Location(m.getCoordinates().x, m.getCoordinates().y));
				if(p.x>30 && p.x<GV.width && p.y>0 && p.y<GV.lp.y){
					GV.processing.image(GV.meteorIcon,p.x-widthHeight/2, p.y-widthHeight/2,widthHeight2,widthHeight2);
				}
			}
		//draw airports
		if(GV.hoursPanel.showAirportsButton.state)
			for(Airport a : GV.data.getAllAirportData()){
				Point2f p = map.locationPoint(new Location(a.getCoordinates().x, a.getCoordinates().y));
				if(p.x>30 && p.x<GV.width && p.y>0 && p.y<GV.lp.y)
					GV.processing.image(GV.airportIcon,p.x-widthHeight/2, p.y-widthHeight/2,widthHeight,widthHeight);
			}
		//draw military bases
		if(GV.hoursPanel.showMilitaryBasesButton.state)
			for(MilitaryBase m : GV.data.getAllMilitaryBase()){
				Point2f p = map.locationPoint(new Location(m.getCoordinates().x, m.getCoordinates().y));
				if(p.x>30 && p.x<GV.width && p.y>0 && p.y<GV.lp.y){
					GV.processing.image(GV.militaryBaseIcon,p.x-widthHeight/2, p.y-widthHeight/2,widthHeight,widthHeight);
				}
			}
		//draw weather stations
		if(GV.hoursPanel.showWeatherStationsButton.state)
			for(WeatherStation w : GV.data.getAllWeatherStations()){
				Point2f p = map.locationPoint(new Location(w.getCoordinates().x, w.getCoordinates().y));
				if(p.x>30 && p.x<GV.width && p.y>0 && p.y<GV.lp.y){
					GV.processing.image(GV.weatherIcon,p.x-widthHeight/2, p.y-widthHeight/2,widthHeight2,widthHeight2);
				}
			}


		if(GV.shapeCategoryColor){
			for(UFO u :GV.ufoToDisplay){
				Point2f p = map.locationPoint(new Location(u.getCoordinates().x, u.getCoordinates().y));
				GV.processing.fill(GV.shapeCol[u.getShape().shape.ordinal()]);
				if(p.x>0 && p.x<GV.width && p.y>0 && p.y<GV.height)
					GV.processing.ellipse(p.x, p.y,circleWidthHeight,circleWidthHeight);
			}	
		}
		else{
			for(UFO u :GV.ufoToDisplay){
				Point2f p = map.locationPoint(new Location(u.getCoordinates().x, u.getCoordinates().y));
				GV.processing.fill(GV.categoryCol[u.getShape().getCategory().ordinal()]);
				if(p.x>0 && p.x<GV.width && p.y>0 && p.y<GV.height)
					GV.processing.ellipse(p.x, p.y, circleWidthHeight, circleWidthHeight); //6,6
			}	

		}




	}

	public void keyReleased() {
		if (GV.processing.key == 'g' || GV.processing.key == 'G') {
			gui = !gui;
		}
		else if (GV.processing.key == 's' || GV.processing.key == 'S') {
			GV.processing.save("modest-maps-app.png");
		}
		else if (GV.processing.key == 'z' || GV.processing.key == 'Z') {
			map.sc = GV.processing.pow(2, map.getZoom());
		}
		else if (GV.processing.key == ' ') {
			map.sc = 2.0;
			map.tx = -128;
			map.ty = -128; 
		}
	}


	// see if we're over any buttons, otherwise tell the map to drag
	public void mouseDragged() {

		map.mouseDragged(); 
		ufoHighLight.state=false;
		ufoHighLight.highLightState=false;
		GV.cluster.createGridData();

	}

	// zoom in or out:
	void mouseWheel(int delta) {
		if (delta < 0) {
			//if(map.sc*1.05<2100)
			map.sc *= 1.05;
			ufoHighLight.state=false;

		}
		else if (delta > 0) {
			if((map.sc * 1.0/1.05)>15){
				map.sc *= 1.0/1.05;
			}
			ufoHighLight.state=false;
			
		}
		
		GV.cluster.createGridData();
		GV.checkTotalData();
		
	}

	public void mouseClicked() {

		if(ufoHighLight.mouseOver()){
			ufoHighLight.mouseClicked();
		}
		else{
			int mX = GV.processing.mouseX;
			int mY = GV.processing.mouseY;

			highLightToDraw = new ArrayList<UFO>();
			int dist = (int) (circleWidthHeight/2);
			//GV.ufoToDisplay
			for(UFO u :GV.ufoToDisplay){
				Point2f p = map.locationPoint(new Location(u.getCoordinates().x, u.getCoordinates().y));

				if(Math.abs(mX-p.x)<dist && Math.abs(mY-p.y)<dist){
					highLightToDraw.add(u);
				}
			}

			if(highLightToDraw.size()>0){
				ufoHighLight.state = true;
				ufoHighLight.createButtons();
			}
			else {ufoHighLight.state = false;ufoHighLight.highLightState=false;}


			boolean found=false;
			if(GV.hoursPanel.showAirportsButton.state){
				for(Airport a:GV.data.airports){
					Point2f p = map.locationPoint(new Location(a.getCoordinates().x, a.getCoordinates().y));
					if(Math.abs(mX-p.x)<dist && Math.abs(mY-p.y)<dist){
						airportHighLightToDraw = a;
						found = true; break;
					}
				}
			}
			if(!found)airportHighLightToDraw = null;
			found=false;
			if(GV.hoursPanel.showMilitaryBasesButton.state){
				for(MilitaryBase m:GV.data.bases){
					Point2f p = map.locationPoint(new Location(m.getCoordinates().x, m.getCoordinates().y));
					if(Math.abs(mX-p.x)<dist && Math.abs(mY-p.y)<dist){
						militaryBaseToDraw = m;
						found = true; break;
					}
				}
			}
			if(!found)militaryBaseToDraw = null;
		}
	}








}